Вы - -й посетитель этой странички 

Простая гостевая книга для школьного сайта

Л.О. Сергеев, г.Москва


   Готовя материал, посвященный языку Perl, для рубрики "Начните с простого", мы прежде всего определили для себя, что простота не должна подразумевать полную тривиальность и бесполезность рассматриваемых примеров. Исходя из этих соображений, мы остановились на задаче, обладающей двумя основными свойствами: во-первых, данная задача является типичной для языка Perl, а, во-вторых, ее решение может быть непосредственно использовано на практике, например, при создании школьного web-сайта. Речь идет о создании простой гостевой книги.

Что представляет собой язык Perl?

   В настоящее время Perl представляет собой универсальный язык программирования высокого уровня. Особенности этого языка таковы, что имеются классы задач, которые на нем решать удобно (часто много удобнее, чем на других языках программирования). Например, Perl очень эффективен для задач, связанных с обработкой строк. Perl также часто используется при решении задач, связанных с программированием для Интернета (одну такую задачу мы рассмотрим в данной статье). Perl - интерпретируемый язык, причем интерпретаторы Perl имеются практически для всех популярных операционных систем (отметим, что большинство интерпретаторов Perl распространяются свободно). Те, кто работает в операционной системе Windows, обычно используют Active Perl, который можно получить, например, на сайте разработчиков www.activestate.com. Думаем, что те, кто работает под Linux и другими клонами Unix, в наших советах по выбору интерпретатора Perl не нуждаются.
   Мы не можем описать типичные проблемы, возникающие при установке Perl под Windows, поскольку нам таковые не известны. Perl устанавливается легко, и конфигурация "по умолчанию", как правило, не требует изменений. В этой конфигурации Perl устанавливается в каталог C:\Perl, а собственно интерпретатором является файл C:\Perl\bin\perl.exe. При установке путь к интерпретатору Perl добавляется в переменную PATH, а файлы с расширением pl ассоциируются с интерпретатором Perl.

Первая программа на языке Perl

   После установки Perl можно немедленно проверить его в работе. Для этого создайте файл, содержащий одну строчку:
   print "\nHello!\n";
   Назовите это файл, например, hello.pl. Это и будет первая простая программа. Для запуска программы передайте ее на вход интерпретатора:
   perl hello.pl
   На экран будет выведена строка Hello! (символами "\n" обозначается переход на новую строку).

CGI-программы

   Аббревиатура CGI расшифровывается как Common Gateway Interface. Суть работы CGI-программ довольно проста. Эти программы исполняются на стороне web-сервера (под управлением web-сервера). Как правило, CGI-программы располагаются в специальном каталоге web-сервера (часто этот каталог называется cgi-bin). Запуск CGI-программ производится сервером при получении пользовательского запроса. Например, если CGI-программа hello.pl расположена в каталоге cgi-bin, на сервере www.domain.ru, она будет запущена при доступе пользователя к следующему URL:
   http://www.domain.ru/cgi-bin/hello.pl.
   При организации web-сервера в локальной сети часто используют не имена хостов, а непосредственно IP-адреса. Если, например, web-сервер уставлен на компьютере с IP-адресом 192.168.0.1 (это типичный случай), URL может выглядеть так:
   http://192.168.0.1/cgi-bin/hello.pl.
   Вывод CGI-программы сервер возвращает пользователю. Приведем пример CGI-программы на языке Perl, которая формирует HTML-страницу и выводит на нее одно слово "Hello!".
   #Простая CGI-программа
   print "Content-type: text/html\n\n";
   print "<html><head><title>Hello!</title>
   </head><body>Hello!</body></html>";

   Посредством первого оператора print выводится заголовок HTML-документа. Этот заголовок сервер всегда отправляет браузеру, для того чтобы тот знал тип данных, которые ему придется получать. Например, GIF-файлу соответствует заголовок "Content-type: image/gif". Заголовок отделяется от документа пустой строкой (это требование стандарта CGI). Дело в том, что заголовок может состоять из нескольких строк (в нашем случае строка одна) и пустая строка является признаком окончания заголовка и начала раздела данных. Именно для вывода пустой строки строка заголовка завершается двумя символами "\n". Второй оператор print формирует простейший HTML-документ.

Организация гостевой книги


   Наша простая гостевая книга будет состоять из двух файлов: guestbook.pl и guestbook.html. Второй файл будет хранить записи, т.е. фактически он является файлом данных, а первый представляет собой программу на языке Perl для управления гостевой книгой.
   Приведем содержимое двух этих файлов и подробно прокомментируем его.
   Начальное содержимое файла guestbook.html (содержимое этого файла будет меняться, поскольку в него будут добавляться записи).
   <h3>Добавление записи в гостевую книгу</h3>
   <form method=post action=/cgi-bin/guestbook.pl>
   <p><input type=text name=name value='Ваше имя'></p>
   <p><textarea name=comment rows=5 cols=50>Комментарий</textarea></p>
   <p><input type=submit value='Готово!'>


   Файл guestbook.pl

# Подключим модуль CGI.pm
use CGI qw/:standard/;
# Функция вывода части HTML-файла до раздела
# данных
sub outhead {
print "<html>";
print "<head>";
print "<title>Простая гостевая книга</title>";
print "</head>";
print "<body>";
print "<h1>Гостевая книга</h1><hr>";
}
# Функция вывода части HTML-файла после
# раздела данных
sub outtail {
print "</body>";
print "</html>";
}
# Функция замены HTML-тегов
sub antihack {
$_[0] =~ s/</</g;
$_[0] =~ s/>/>/g;
}
# Основная программа
# Если параметры имеются, дописываем их
# в файл
if (param()){
open GB, ">> guestbook.html";
$name=param('name'); antihack($name);
$comment=param('comment'); antihack($comment);
print GB "\n<p>";
$lt=localtime; print GB "\n$lt<br>";
print GB "\n<b>Имя:</b> $name<br>";
print GB "\n<b>Комментарий</b>: $comment";
print GB "\n<hr>";
close GB;
}
# В любом случае выводим содержимое файла
print "Content-type:text/html\n\n";
&outhead;
open GB, "< guestbook.html";
while (<GB>) { print $_;}
close GB;
&outtail;

Страница с гостевой книгой в браузере


   Сначала прокомментируем содержимое файла guestbook.html. Как мы уже говорили, этот файл является файлом данных, в котором хранятся записи гостевой книги. Кроме этого, в начале файла находится форма, посредством которой происходит добавление записей. Так, после добавления в гостевую книгу двух записей файл guestbook.html будет содержать следующий текст:
<h3>Добавление записи в гостевую книгу</h3>
<form method=post action=/cgi-bin/guestbook.pl>
<p><input type=text name=name value='Ваше имя'></p>
<p><textarea name=comment rows=5 cols=50>Комментарий</textarea></p>
<p><input type=submit value='Готово!'>
</form>
<hr>
<p>Wed Jan 23 18:14:12 2002<br>
<b>Имя:</b> Первый пользователь<br>
<b>Комментарий</b>: Комментарий первого пользователя
<hr>
<p>Wed Jan 23 18:14:26 2002<br>
<b>Имя:</b> Второй пользователь<br>
<b>Комментарий</b>: Комментарий второго пользователя

   В форме указано, что при нажатии на кнопку 'Готово!' следует вызвать программу guestbook.pl. При этом, в соответствии с правилами обработки форм, данной программе передаются значения двух полей - name и comment.
   Перейдем к рассмотрению программы guestbook.pl. В первой строке подключается модуль CGI.pm, содержащий функции, использумые в CGI-программах. На самом деле нам понадобится единственная функция param, и большинство программистов предпочли бы в такой ситуации обойтись без подключения модуля. Но это несколько усложнит текст, поэтому мы избрали не самый изящный, но простой вариант.
   Функции (подпрограммы) outhead и outtail служат для вывода начала (части до раздела данных) и конца HTML-документа. Подпрограммы могут располагаться в любой части программы; то, что мы разместили их в начале, не является обязательным.
   Следующая подпрограмма antihack, на наш взгляд, является самой интересной. Какой бы простой не была наша гостевая книга, мы все же не хотим наступать на общеизвестные "грабли". "Грабли" эти заключаются в предоставлении возможности пользователю использовать HTML-теги. Это позволит пользователям, например, помещать в гостевую книгу скрипты и прочие потенциально опасные фрагменты. Для исключения такой возможности достаточно заменить в тексте, вводимом пользователем, символы "<" и ">" на строки "<" и ">" соответственно. При этом отображение введенного пользователем текста не изменится, но HTML-теги будут интерпретироваться как обычный текст. Для того чтобы понять, как работает функция antihack, нужно разобраться с целым рядом вопросов.
   Вопрос первый - о скалярных переменных и массивах. В языке Perl имеются не только скалярные переменные, но и массивы (в Perl имеются и другие структурированные типы, но они сейчас нас не интересуют). Имена скалярных переменных всегда начинаются с символа "$" (примеры: $a, $a1, $_), имена массивов - с символа "@" (примеры: @a, @a1, @_). Следует обратить внимание на то, что элементы массивов являются скалярами, поэтому при обращении к элементу массива следует использовать символ "$" (примеры: $a[0], $a1[0], $_[0]). Мы не случайно привели примеры "странных" имен ($_ и @_). Такого рода имена в Perl допустимы, причем некоторые переменные с подобными "странными" именами используются для специальных целей. Пример этого мы сейчас увидим.
   Вопрос второй - о передаче параметров в подпрограммы. Передача параметров в подпрограммы осуществляется через специальный массив @_. Если мы вызываем подпрограмму f от трех переменных $a, $b, $c: f($a, $b, $c), этим переменным будут соответствовать элементы массива @_: $_[0], $_[1] и $_[2]. Передача параметров производится по ссылке (т.е. все изменения элементов массива @_ отражаются на фактических параметрах подпрограммы).
   Вопрос третий - об операции замены в строке. Это наиболее сложный вопрос. Он имеет отношение к так называемым "регулярным выражениям", и для его рассмотрения не хватит никакой статьи (впрочем, в ближайших номерах "Информатики" готовится к печати статья, посвященная регулярным выражениям). Поэтому мы поступим следующим образом: объясним ровно то, что написано в функции antihack.
   Операция замены в строке в языке Perl имеет следующий вид:
   $строковая_переменная =~ s/что_заменять/на_что_заменять/модификаторы.
   В нашем случае (в функции antihack) используются:
   $строковая_переменная - $_[0];
   что_заменять - символы "<" (в первом случае) и ">" (во втором случае);
   на_что_заменять - строки "<" и ">" соответственно.
   Модификаторы не являются обязательными, но мы использовали один модификатор "g" (global), для того чтобы замена производилась по всему тексту, а не единожды.
   Как уже было сказано выше, в результате такой замены в тексте, введенном пользователем, будут "подавлены" все HTML-теги, например, строка "<script>" превратится в строку "<script>".
   Закончив с функциями, перейдем к рассмотрению кода основной программы. В условном операторе несколько раз используется функция param. Эта функция содержится в модуле CGI (мы уже отмечали, что только из-за этой функции мы подключали модуль CGI). При вызове без параметров эта функция возвращает логическое значение - были ли переданы в программу параметры. Мы не проверяем имена переданных параметров и считаем, что если уж параметры были, то это те параметры, которые нам нужны, - name и comment. По факту наличия или отсутствия параметров мы определяем и то, каким образом была вызвана программа guestbook.pl. Она может быть вызвана при запросе пользователем соответствующего URL (в этом случае программа не получает параметров и, пропуская раздел модификации файла guestbook.html, лишь выводит содержимое гостевой книги) или при заполнении формы - при нажатии на кнопку submit (в этом случае программа получит параметры name и comment и выполнит модификацию файла guestbook.html). (Отметим, что избранный нами способ проверки механизма вызова программы, мягко говоря, не совсем правильный. Было бы лучше проверять метод вызова программы guestbook.pl - GET или POST. Но это, как и многое другое, может увести нас слишком далеко.)
   В настоящей гостевой книге такую проверку следует выполнять хотя бы из соображений безопасности. В операторе
   open GB, ">> guestbook.html";
   файл guestbook.html открывается для дозаписи (append). (Режимом доступа к файлу можно управлять посредством символов, которые ставятся перед его именем. В частности, файл можно открыть для чтения - "<", для записи - ">" и, как в нашем случае, для дозаписи - ">>".)
   Первый параметр оператора open - GB - идентификатор файла.
   В следующих операторах мы получаем (снова посредством функции param) значения параметров name и comment, обрабатываем их функцией antihack и записываем в файл guestbook.html, добавляя элементы HTML-разметки.
   После модификации файла guestbook.html мы приступаем к формированию вывода. В первом операторе print выводится заголовок, после него, как уже было сказано выше, требуется вывести пустую строку. Далее вызывается подпрограмма для вывода части HTML-файла до раздела данных. Обратите внимание на способ вызова подпрограмм в Perl. Затем открывается для чтения файл guestbook.html и его содержимое выводится построчно. Здесь мы еще раз встречаемся с использованием специальной переменной с именем $_. Обсудим этот цикл подробнее. Чтение строки в переменную $s из файла, связанного с идентификатором ID, выполняется следующим образом: $s = ;. Одно из многочисленных умолчаний языка Perl заключается в том, что, если имя переменной не указано, чтение производится в переменную с именем $_. Таким образом, развернутая запись оператора цикла в нашей программе следующая:
   while ($_=) { print $_;}
   Мы использовали сокращенную запись потому, что, во-первых, хотели продемонстрировать использование специальной переменной $_, а во-вторых, именно так и пишут на Perl. Именно такую запись вы скорее всего и встретите в книгах.
   Кстати, о книгах. Для начального знакомства с языком Perl мы можем порекомендовать классическую и, возможно, лучшую из имеющихся книгу Р.Л. Шварца и Т.Кристиансена "Изучаем Perl". Эта книга вышла на русском языке в 1998 г. (на языке оригинала она была издана в 1997 г.) и выдержала множество переизданий. В магазинах книгу "Изучаем Perl" легко узнать по замечательному изображению ламы на обложке.